#include "ReflectRefractFX.h"

ReflectRefractFX::ReflectRefractFX(ID3D11Device* device)
	: AbstractFX(device, L"FX/ReflectRefract.fxo")
{
	InitInputLayout(device);
	InitShaderVariablePointers();
}

ReflectRefractFX::~ReflectRefractFX()
{}

void ReflectRefractFX::InitInputLayout(ID3D11Device* device)
{
	const D3D11_INPUT_ELEMENT_DESC inputLayout[] = 
	{
		{"POSITION", 0, DXGI_FORMAT_R32G32B32_FLOAT,    0, 0,  D3D11_INPUT_PER_VERTEX_DATA, 0},
		{"NORMAL",   0, DXGI_FORMAT_R32G32B32_FLOAT,    0, 12, D3D11_INPUT_PER_VERTEX_DATA, 0},
		{"TEXCOORD", 0, DXGI_FORMAT_R32G32_FLOAT,    0, 24, D3D11_INPUT_PER_VERTEX_DATA, 0}
	};

	CreateInputLayout(device, inputLayout, 3);
}

void ReflectRefractFX::InitShaderVariablePointers()
{
	worldVar         = effect->GetVariableByName("world")->AsMatrix();
	worldInvTransVar = effect->GetVariableByName("worldInvTrans")->AsMatrix();
	worldViewProjVar = effect->GetVariableByName("worldViewProj")->AsMatrix();
	texTransformVar  = effect->GetVariableByName("texTransform")->AsMatrix();

	rtWidthVar  = effect->GetVariableByName("rtWidth")->AsScalar();
	rtHeightVar = effect->GetVariableByName("rtHeight")->AsScalar();

	materialVar        = effect->GetVariableByName("mat");
	eyePosVar          = effect->GetVariableByName("eyePosW")->AsVector();
    direcLightVar	   = effect->GetVariableByName("dLight");
	direcLightCountVar = effect->GetVariableByName("dLightCount")->AsScalar();

	//Tile Forward System
	llbVar   = effect->GetVariableByName("LightListBuffer")->AsShaderResource();
	llibVar  = effect->GetVariableByName("LightListIndexBuffer")->AsShaderResource();
	llsebVar = effect->GetVariableByName("LightListStartEndBuffer")->AsShaderResource();

	//Texture map variable
	texMapVar = effect->GetVariableByName("TextureMap")->AsShaderResource();
	
	//Hemispherical lighting
	hemiColDownVar = effect->GetVariableByName("HemiColDown")->AsVector();
	hemiColRangeVar = effect->GetVariableByName("HemiColRange")->AsVector();
	
	//SSAO
	worldViewVar = effect->GetVariableByName("WorldView")->AsMatrix();
	ssaoMapVar = effect->GetVariableByName("SSAOMap")->AsShaderResource();
	ssaoWorldViewProjTexVar = effect->GetVariableByName("SSAOWorldViewProjTex")->AsMatrix();

	//Environment map
	envMapVar = effect->GetVariableByName("EnvironmentMap")->AsShaderResource();

	//Shadow map
	shadowMapVar = effect->GetVariableByName("ShadowMap")->AsShaderResource();
	shadowMapViewVar = effect->GetVariableByName("ShadowMapView")->AsMatrix();
	shadowMapProjVar = effect->GetVariableByName("ShadowMapProj")->AsMatrix();
	shadowMapToTexVar = effect->GetVariableByName("ShadowMapToTex")->AsMatrix();

	//ClipPlane
	clipPlaneVar = effect->GetVariableByName("ClipPlane")->AsVector();
}

void ReflectRefractFX::SetCBufferPerObject(CXMMATRIX& world, 
		CXMMATRIX& worldInvTrans, CXMMATRIX& worldViewProj, 
		CXMMATRIX& texTrans, Material& mat, 
		CXMMATRIX& worldView)
{
	worldVar->SetMatrix(reinterpret_cast<const float*>(&world));
	worldInvTransVar->SetMatrix(reinterpret_cast<const float*>(&worldInvTrans));
	worldViewProjVar->SetMatrix(reinterpret_cast<const float*>(&worldViewProj));
	texTransformVar->SetMatrix(reinterpret_cast<const float*>(&texTrans));

	materialVar->SetRawValue(&mat, 0, sizeof(Material));

	worldViewVar->SetMatrix(reinterpret_cast<const float*>(&worldView));
}

void ReflectRefractFX::SetRTDimensions(unsigned width, unsigned height)
{
	rtWidthVar->SetInt(width);
	rtHeightVar->SetInt(height);
}

void ReflectRefractFX::SetLightingData(XMFLOAT3& eye, 
	DirectionalLight* dLights, unsigned dLightCount,
	ID3D11ShaderResourceView* lightListIndexBuffer, 
	ID3D11ShaderResourceView* lightListStartEndBuffer)
{
	eyePosVar->SetRawValue(&eye, 0, sizeof(XMFLOAT3));
	
	//Cap Direc Lights to 3.
	if (dLightCount > MAX_DIRECTIONAL_LIGHT_COUNT)
		dLightCount = MAX_DIRECTIONAL_LIGHT_COUNT;
	direcLightVar->SetRawValue(dLights, 0, sizeof(DirectionalLight) * dLightCount);
	direcLightCountVar->SetInt(dLightCount);

	//Update LLIB, LLSEB
	llibVar->SetResource(lightListIndexBuffer);
	llsebVar->SetResource(lightListStartEndBuffer);
}

void ReflectRefractFX::SetLightListBuffer(ID3D11ShaderResourceView* lightListBuffer)
{
	llbVar->SetResource(lightListBuffer);
}

void ReflectRefractFX::SetTextureMap(ID3D11ShaderResourceView* textureMap)
{
	texMapVar->SetResource(textureMap);
}

void ReflectRefractFX::SetHemisphericalData(XMFLOAT3 &hemiColDown, XMFLOAT3 &hemiColRange)
{
	hemiColDownVar->SetRawValue(&hemiColDown, 0, sizeof(XMFLOAT3));
	hemiColRangeVar->SetRawValue(&hemiColRange, 0, sizeof(XMFLOAT3));
}

void ReflectRefractFX::SetSSAOData(ID3D11ShaderResourceView* ssaoTex, CXMMATRIX &transform)
{
	ssaoMapVar->SetResource(ssaoTex);
	ssaoWorldViewProjTexVar->SetMatrix(reinterpret_cast<const float*>(&transform));
}

void ReflectRefractFX::SetEnvironmentMap(ID3D11ShaderResourceView* envCubeMap)
{
	envMapVar->SetResource(envCubeMap);
}

void ReflectRefractFX::SetShadowMap(ID3D11ShaderResourceView* shadowMap)
{
	shadowMapVar->SetResource(shadowMap);
}

void ReflectRefractFX::SetShadowMapMatricies(CXMMATRIX &view, CXMMATRIX &proj, CXMMATRIX &toTex)
{
	shadowMapViewVar->SetMatrix(reinterpret_cast<const float*>(&view));
	shadowMapProjVar->SetMatrix(reinterpret_cast<const float*>(&proj));
	shadowMapToTexVar->SetMatrix(reinterpret_cast<const float*>(&toTex));
}

void ReflectRefractFX::SetClipPlane(XMFLOAT4& clipPlane)
{
	clipPlaneVar->SetFloatVector(reinterpret_cast<const float*>(&clipPlane));
}